package com.laomuji.android.mvvm.http.observer

import com.laomuji.android.mvvm.http.exception.ExceptionCode
import io.reactivex.Observable
import io.reactivex.Observer
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.Disposable
import io.reactivex.schedulers.Schedulers
import retrofit2.HttpException
import java.net.SocketTimeoutException
import java.net.UnknownHostException

/**
 * 基础响应监听,处理一些通用的操作
 * @author laomuji666
 * @since 2024/2/20
 */
abstract class BaseObserver<T> : Observer<T> {
    /**
     * 响应成功
     * @param entity 响应内容转换的实体对象
     */
    abstract fun onSuccess(entity: T)

    /**
     * 响应失败
     * @param code 错误码
     * @param msg 错误内容
     * @param e 异常
     */
    abstract fun onFail(code: String, msg: String, e: Throwable)


    /**
     * 响应成功
     * @param entity 响应内容转换的实体对象
     */
    override fun onNext(entity: T & Any) {
        onSuccess(entity)
    }

    /**
     * 响应失败
     * 处理Http错误
     * @param e 响应失败的异常
     */
    override fun onError(e: Throwable) {
        when (e) {
            is HttpException -> {
                //响应码不为200
                onFail(e.code().toString(), e.message(), e)
            }

            is SocketTimeoutException -> {
                //连接超时
                onFail(ExceptionCode.SOCKET_TIMEOUT, "Socket Timeout", e)
            }

            is UnknownHostException -> {
                //端口号解析错误
                onFail(ExceptionCode.HOST_UNKNOWN, "Host Unknown", e)
            }

            else -> {
                //未知的异常
                onFail(ExceptionCode.UNDEFINE, "Undefine Error", e)
            }
        }
    }

    /**
     * 获取响应失败的响应体
     * @param e 响应失败的异常
     */
    protected open fun getErrResponse(e: HttpException): String? {
        return try {
            val response = e.response() ?: return null
            val responseBody = response.errorBody() ?: return null
            responseBody.string()
        } catch (ex: Exception) {
            null
        }
    }

    override fun onComplete() {}
    override fun onSubscribe(d: Disposable) {}
}

fun <T>Observable<T>.observeOnIO():Observable<T>{
    return this.subscribeOn(Schedulers.io()).observeOn(Schedulers.io())
}

fun <T>Observable<T>.observeOnMain():Observable<T>{
    return this.subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread())
}